package com.ebelter.btlibrary.btble.impl.ecg;


import com.ebelter.btlibrary.btble.ble.bluetooth.callback.ConnectCallback;
import com.ebelter.btlibrary.btble.ble.bluetooth.device.impl.BleMessageAnalyser;
import com.ebelter.btlibrary.btble.ble.bluetooth.device.impl.Channel;
import com.ebelter.btlibrary.btble.ble.model.BtAck;
import com.ebelter.btlibrary.btble.impl.ecg.callback.EcgResultCallback;
import com.ebelter.btlibrary.btble.impl.ecg.model.EcgResult;
import com.ebelter.btlibrary.btble.impl.scale.callback.IMeasureResultCallback;
import com.ebelter.btlibrary.btble.impl.scale.callback.WeightUnitChangedCallback;
import com.ebelter.btlibrary.btble.impl.scale.common.ScaleAck;
import com.ebelter.btlibrary.btble.impl.scale.model.FatResult;
import com.ebelter.btlibrary.btble.impl.scale.model.OfflineMeasureResult;
import com.ebelter.btlibrary.btble.impl.scale.model.Scale;
import com.ebelter.btlibrary.btble.impl.scale.model.ScaleCommand;
import com.ebelter.btlibrary.btble.impl.scale.model.ScaleMeasureResult;
import com.ebelter.btlibrary.btble.impl.scale.model.ScaleUser;
import com.ebelter.btlibrary.btble.impl.scale.model.WeightUnit;
import com.ebelter.btlibrary.btble.impl.scale.upgrade.IFirmwareUpgradeCallback;
import com.ebelter.btlibrary.btble.util.MeasureResultAnalyzer;
import com.ebelter.btlibrary.util.ULog;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;

/**
 * 心电数据解析器
 * Created by Sergio Pan on 2017/12/8.
 */

public class EcgMessageAnalyser extends BleMessageAnalyser {

    private static final String TAG = "EcgMessageAnalyser";

    private static EcgMessageAnalyser instance = new EcgMessageAnalyser();

    //数据解析后的各种回调
    private EcgResultCallback measureResultCallback;
    /**** 是否正在触摸心电块 ***/
    private boolean isTouching = true;

    private EcgMessageAnalyser() {
//        recordSet.
    }

    public static EcgMessageAnalyser getInstance() {
        return instance;
    }


    public void registerMeasureResultCallback(EcgResultCallback callback) {
        this.measureResultCallback = callback;
    }


    /**
     * 解密数据
     *
     * @param data
     * @return
     */
    @Override
    protected byte[] decrypt(byte[] data) {
//        ULog.i(TAG, "-------decrypt--------data = " + getArrayString(data));
        //TODO 如若是加密数据，在此做解密处理,如若非加密数据，可不重写此方法

        return data;
    }

    /**
     * 开始解析
     *
     * @param data
     * @return
     */
    @Override
    protected void analyze(Channel channel, byte[] data) {
        ULog.i(TAG, "-------analyze----before filter----data = " + getArrayString(data));
        switch (channel) {
            case CHANNEL_0:
                receiveOnChannel_0(data);
                break;
            case CHANNEL_1:
                receiveOnChannel_1(data);
                break;
            case CHANNEL_2:
                receiveOnChannel_2(data);
                break;
        }
    }

    private void receiveOnChannel_0(byte[] data) {
        //过滤
//        if (data.length < 2 || data[0] != dataHeaderReceive || data.length != (data[1] & 0xff) + 3) {
//            return;
//        }
//        ULog.i(TAG, "-------analyze---after filter-----data = " + getArrayString(data));
        //业务码

        if (!isTouching) {
            return;
        }
        ULog.i(TAG, "-------receiveOnChannel_0-------data = " + getArrayString(data));
        doEcgResult(data);
    }

    private void receiveOnChannel_1(byte[] data) {
        ULog.i(TAG, "-------receiveOnChannel_1--------data = " + getArrayString(data));
        if (data[0] > 0) {
            isTouching = true;
        } else {
            isTouching = false;
        }
        doTouchStatus(data);
    }

    private void receiveOnChannel_2(byte[] data) {
        ULog.i(TAG, "-------receiveOnChannel_2-------data = " + getArrayString(data));
        doBatteryPower(data);
    }


    /**
     * 收到心电数据
     */
    private void doEcgResult(byte[] data) {


        List<Float> adcs = getAdcResult(data);
        ULog.i(TAG, "-----doEcgResult------receive ECG measure result. adcs.size() = " + adcs.size());
        EcgResult result = new EcgResult();
        result.setResults(adcs);
        //秤唤醒后，需设置用户信息
        if (measureResultCallback != null) {
            measureResultCallback.onReceiveResult(result);
        }

    }

    /**
     * 触摸状态
     *
     * @param data
     */
    private void doTouchStatus(byte[] data) {
        ULog.i(TAG, "-----doTouchStatus------receive touch status. data = ");
        boolean isTouching = false;
        if (measureResultCallback != null) {
            measureResultCallback.onReceiveTouchStatus(isTouching);
        }
    }

    /**
     * 电池电量
     *
     * @param data
     */
    private void doBatteryPower(byte[] data) {
        ULog.i(TAG, "-----doBatteryPower------receive battery power.data = ");
        int power = 0;
        if (measureResultCallback != null) {
            measureResultCallback.onReceiveBatteryPower(power);
        }
    }


    private List<Float> getAdcResult(byte[] data) {
        List<Float> results = new ArrayList<>();
        int cycle = getMultCycle(8, 12);
        int count = (data.length - 2) / cycle;
        if ((data.length - 2) % cycle != 0) {
            count += 1;
        }
        for (int i = 0; i < count; i++) {
            int temp0 = data[i * cycle + 2] & 0xff;
            int temp1 = data[i * cycle + 3] & 0xff;
            int temp1_1 = data[i * cycle + 3] & 0xff;
            int temp2 = data[i * cycle + 4] & 0xff;
            //第二个字节，右移4位，与第一字节拼接
            int result0 = ((temp0 << 4) | (temp1 >> 4)) & 0x0fff;
            //第二个字节，去高4位后，左移8位，与第三字节拼接
            int result1 = (((temp1_1 & 0x0f) << 8) | temp2) & 0x0fff;

            results.add(getVoltage(result0)/1000.0f);
            results.add(getVoltage(result1)/1000.0f);

            ULog.i(TAG, "-------getAdcResult-----temp0 = " + Integer.toBinaryString(temp0) + ", temp1 = " + Integer.toBinaryString(temp1) + ", temp2 = " + Integer.toBinaryString(temp2));
            ULog.i(TAG, "-------getAdcResult-----result0 = " + Integer.toBinaryString(result0) + ", result0 = " + result0 + ", result1 = " + Integer.toBinaryString(result1) + ", result1 = " + result1);
        }
        return results;
    }

    /**
     * 获取电压， mv
     *
     * @return
     */
    private int getVoltage(int adc) {
        int bbb = 1 << 12;
        return 4300 * adc / (bbb - 1) - 1270;
    }

    /**
     * 获取a位转b位的周期
     *
     * @param a
     * @param b
     * @return
     */
    private int getMultCycle(int a, int b) {
        int aa = a;
        int bb = b;
        int m = aa % bb;
        while (m != 0) {
            aa = bb;
            bb = m;
            m = aa % bb;
        }
        return (a * b / bb) / Math.min(a, b);
    }


    public int getDecryptValue(byte a, byte b) {
        int aa = a & 0xff;
        int bb = b & 0xff;
        return (bb << 8) | aa;
    }


    @Override
    public void onRelease() {
        super.onRelease();


    }
}
